package cn.lxh.mq.tx;

import cn.lxh.constants.Constants;
import cn.lxh.pojo.app.bo.PayOrderBo;
import cn.lxh.pojo.domain.Order;
import cn.lxh.service.IOrderService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;

import java.nio.charset.StandardCharsets;

/**
 * @author lxh Create Time: 2024/1/15 18:11
 * 事务监听器
 */
// 表明这个一个生产端的消息监听器，需要配置监听的事务消息生产者组
@RocketMQTransactionListener(txProducerGroup = Constants.MQ.TX_PAY_ORDER_PRODUCER)
public class PayOrderTxListener implements RocketMQLocalTransactionListener {

    @Autowired
    private IOrderService iOrderService;

    /**
     * 执行本地事务的方法
     * @param message 消息对象
     * @param o 扩展参数
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        try {
            Order order = (Order) o;
            // 保存order
            iOrderService.updateById(order);
            // 执行本地事务方法, 就是做数据库
            return RocketMQLocalTransactionState.COMMIT; // 修改成功, 提交
        } catch (Exception e) {
            return RocketMQLocalTransactionState.ROLLBACK; // 修改失败, 回滚
        }}

    /**
     * 检查本地事务的方法
     * @param message 消息对象
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        // 判断本地事务是否执行成功, 就是去数据库查是否有executeLocalTransaction方法执行之后的结果

        // 字节数组转字符串
        String s = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
        // 字符串转对象
        PayOrderBo payload = JSON.parseObject(s, PayOrderBo.class);
        // 根据订单号查询订单
        Order order = iOrderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderNo, payload.getOrderNo()));
        // 订单状态不是待支付就回滚
        if(order.getStatus() != Constants.Order.ORDER_STATUS_NOT_PAY){
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        return RocketMQLocalTransactionState.COMMIT;
    }
}
